/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package App;

import generated.BoardType;
import generated.CardType;
import generated.MazeCom;
import generated.MoveMessageType;
import generated.PositionType;
import generated.TreasureType;
import java.util.ArrayList;
import networking.MazeComMessageFactory;
import server.Board;
import server.Position;
import utils.BoardTypeAnalyser;

/**
 *
 * @author rebecca.badziong
 */
public class CalculationForThread implements Runnable {

    private ReturnObjekt returnObjekt;
    private final int currendUserId;
    private final PositionType shiftposition;
    private final PositionType myCurrentPosition;
    private BoardType board;
    private final CardType shift;
    private final TreasureType treasure;
    private int value = 0;
    private boolean[][] visited;
    private PositionType positonOfTreasure;
    private PositionType bestPosition; 

    public CalculationForThread(int currendUserId, PositionType shiftposition, PositionType myCurrentPosition, BoardType board, CardType shift, TreasureType treasure) {
        this.currendUserId = currendUserId;
        this.shiftposition = shiftposition;
        this.myCurrentPosition = myCurrentPosition;
        this.board = board;
        this.shift = shift;
        this.treasure = treasure;
        this.value = 42;
        visited = new boolean[7][7];
        for (int i = 0; i < 7; i++) {
            for (int j = 0; j < 7; j++) {
                visited[i][j] = false;
            }
        }
    }

    private int goThroughLabirinth(PositionType currentCard, CardType startType, BoardType board) {
        int col = currentCard.getCol();
        int row = currentCard.getRow();
        int tempValue;
        if (!(visited[row][col])) {
            visited[row][col] = true;
            tempValue = Math.abs(currentCard.getCol()-positonOfTreasure.getCol())+Math.abs(currentCard.getRow()-positonOfTreasure.getCol());
            if (tempValue == 0) {
                return 1;
            } else {
                int[] neighbor = {0, 0, 0, 0};
                if (startType.getOpenings().isTop()) {
                    if (currentCard.getRow() != 0) {
                        CardType nextCard = BoardTypeAnalyser.getCard(row-1, col, board);
                        if (nextCard.getOpenings().isBottom()){
                            PositionType nextPos = new PositionType();
                            nextPos.setRow(currentCard.getRow()-1);
                            nextPos.setCol(currentCard.getCol());
                            return goThroughLabirinth(nextPos, nextCard, board);
                        }else{
                            neighbor[0] = -1;
                        }
                    } else {
                        neighbor[0] = -1;
                    }
                } else {
                    neighbor[0] = -1;
                }
                
                if (startType.getOpenings().isRight()) {
                    if (currentCard.getCol() != 6) {
                        CardType nextCard = BoardTypeAnalyser.getCard(row, col+1, board);
                        if (nextCard.getOpenings().isLeft()){
                            PositionType nextPos = new PositionType();
                            nextPos.setRow(currentCard.getRow());
                            nextPos.setCol(currentCard.getCol()+1);
                            return goThroughLabirinth(nextPos, nextCard, board);
                        }else{
                            neighbor[1] = -1;
                        }
                    } else {
                        neighbor[1] = -1;
                    }
                } else {
                    neighbor[1] = -1;
                }
                
                if (startType.getOpenings().isBottom()) {
                    if (currentCard.getRow() != 6) {
                        CardType nextCard = BoardTypeAnalyser.getCard(row+1, col, board);
                        if (nextCard.getOpenings().isTop()){
                            PositionType nextPos = new PositionType();
                            nextPos.setRow(currentCard.getRow()+1);
                            nextPos.setCol(currentCard.getCol());
                            return goThroughLabirinth(nextPos, nextCard, board);
                        }else{
                            neighbor[2] = -1;
                        }
                    } else {
                        neighbor[2] = -1;
                    }
                } else {
                    neighbor[2] = -1;
                }
                
                if (startType.getOpenings().isRight()) {
                    if (currentCard.getCol()!= 0) {
                        CardType nextCard = BoardTypeAnalyser.getCard(row, col-1, board);
                        if (nextCard.getOpenings().isLeft()){
                            PositionType nextPos = new PositionType();
                            nextPos.setRow(currentCard.getRow());
                            nextPos.setCol(currentCard.getCol()-1);
                            return goThroughLabirinth(nextPos, nextCard, board);
                        }else{
                            neighbor[3] = -1;
                        }
                    } else {
                        neighbor[3] = -1;
                    }
                } else {
                    neighbor[3] = -1;
                }
                
                if (tempValue < value){
                    this.value = tempValue;
                    bestPosition.setRow(currentCard.getRow());
                    bestPosition.setCol(currentCard.getCol());
                }
                int maxNeighbor = 0;
                for (int i = 0; i < 4; i++) {
                    if (neighbor[i] > maxNeighbor) {
                        maxNeighbor = neighbor[i];
                    }
                }
                return maxNeighbor;
            }
        } else {
            return -1;
        }
    }

    @Override
    public void run() {
        MoveMessageType move = new MoveMessageType();
        move.setNewPinPos(myCurrentPosition);
        move.setShiftCard(shift);
        move.setShiftPosition(shiftposition);
        this.board = BoardTypeAnalyser.getNextTurn(move, this.board);
        CardType startCard = BoardTypeAnalyser.getCard(myCurrentPosition.getRow(), myCurrentPosition.getCol(), this.board);
        positonOfTreasure = BoardTypeAnalyser.getTreasurePosition(treasure, board);
        bestPosition = myCurrentPosition;
        this.goThroughLabirinth(myCurrentPosition, startCard, board);
        
        MoveMessageType doMove = new MoveMessageType();
        doMove.setShiftCard(shift);
        doMove.setShiftPosition(shiftposition);
        doMove.setNewPinPos(bestPosition);
        MazeCom maze = new MazeCom();
        maze.setMoveMessage(doMove);
        returnObjekt = new ReturnObjekt(maze, value);
        MoveFactory.moves.add(this.returnObjekt);

    }

    public ReturnObjekt getReturnObjekt() {
        return this.returnObjekt;
    }

}
